package com.cnbm.wcsbasic.dispatch;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.cnbm.wcsbasic.protocol.netty.s7.s7connector.enmuc.S7Client;
import com.cnbm.wcsbasic.protocol.netty.s7.s7connector.type.PlcVar;
import com.cnbm.wcsbasic.dispatch.constant.QGSConstant;
import com.cnbm.wcsbasic.dispatch.entity.JXSInfoCallBack;
import com.cnbm.wcsbasic.dispatch.enums.manipulator.JXSPlc2WcsVar;
import com.cnbm.wcsbasic.dispatch.enums.manipulator.JXSWcs2PlcVar;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @Desc: ""
 * @Author: caixiang
 * @DATE: 2022/12/23 12:33
 */
@Component
@Order(value = 1)
public class JXSTask implements ApplicationRunner {
    private static final Logger logger = LoggerFactory.getLogger("JXSLOGGER");



    public JXSTask(){
        this.agvPort1 = Executors.newScheduledThreadPool(1);
        this.agvPort2 = Executors.newScheduledThreadPool(1);
        this.agvPort3 = Executors.newScheduledThreadPool(1);
        this.agvPort4 = Executors.newScheduledThreadPool(1);
    }

    private ScheduledExecutorService agvPort1;
    private ScheduledExecutorService agvPort2;
    private ScheduledExecutorService agvPort3;
    private ScheduledExecutorService agvPort4;




    /**
     * return
     *          成功： 返回相应的object对象
     *          失败： 返回null
     * */
    private Object read(S7Client s7Client, JXSPlc2WcsVar var) {
        try {
            return s7Client.read(var.getArea(), var.getAreaNumber(), var.getByteOffset(), var.getBitOffset(), var.getLength(), var.getStrSize(), var.getType());
        }catch (Throwable e){
            logger.info("host:"+s7Client.getHost()+" ; read 操作出现问题: {}",e.getMessage(),e);
            return null;
        }
    }

    private void write(S7Client s7Client, JXSWcs2PlcVar var, Object newValue) {
        if(var.getType().equals(PlcVar.STRING_Array)){
            String[] s = (String[])newValue;
            String[] ss = (String[])newValue;
            if(s.length > var.getLength() ){
                ss = new String[var.getLength()];
                for(int i=0;i< var.getLength();i++){
                    ss[i] = s[i];
                }
            }
            s7Client.write(var.getArea(), var.getAreaNumber(), var.getByteOffset(), var.getBitOffset(), var.getStrSize(), var.getType(),ss);
        }else {
            s7Client.write(var.getArea(), var.getAreaNumber(), var.getByteOffset(), var.getBitOffset(), var.getStrSize(), var.getType(),newValue);
        }
    }


    public static void main(String[] args) throws InterruptedException {
        ScheduledExecutorService agvPort1 = Executors.newScheduledThreadPool(1);
        final int[] i = {0};
        agvPort1.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
//                try {
//                    try {
//                        System.out.println("小于5");
//
//                    }catch (Exception e){
//                        System.out.println("进入异常了");
//                        throw new RuntimeException();
//                    }
//                }catch (Throwable e){
//                    System.out.println("位置异常： "+e.getMessage());
//                }
                try {
                    if(i[0] <10){
                        i[0]++;
                        System.out.println("小于5");
                        Thread.sleep(1000);
                    }else {
                        throw new Exception("1");
                    }


                }catch (Exception e){
                    System.out.println("进入异常了");
                    throw new RuntimeException();
                }
            }
        },1,1, TimeUnit.SECONDS);

        while (true){

            System.out.println("is termin : "+agvPort1.isShutdown());
            Thread.sleep(1000);
        }
    }



    /* *
     *
     * status
     *      10   初始值
     *      -2   s7 数据采集失败
     *      100  任务成功完成
     *      101  任务被人为取消，取消的原因看 content ，tip:目前没有报错101 因为当设备故障后 我程序是阻塞住等成功标志位的。
     * */
    @Override
    public void run(ApplicationArguments args) throws Exception {

        agvPort1.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    try {
                        logger.info("agv1 port--- 开始");
                        JXSInfoCallBack build = new JXSInfoCallBack();
                        build.setStatus(10);
                        build.setAgvPort("E01_1");

                        //调度逻辑 ------------------------------------- 开始 -------------------------------------
                        //替换waitingForTarget     开始
                        //Integer missionState = waitingForTarget(JXSPlc2WcsVar.AGV1_MissionState, 3);
                        //todo 注意：如果是后台一直轮询的业务，不能一开始 就waitingForTarget(xxx) ,要 read(xx) + return 方式
                        // 因为，这里高压 轮询，就算设备连上线了，也建立不了连接的，因为这里还没有建立成功，就被另外地方 set null了。
                        Integer missionState = (Integer) read(S7Client.S7_JXS,JXSPlc2WcsVar.AGV1_MissionState);
                        if(missionState == null){
                            logger.info("失败"+" --- "+" wcs agvPort1 与设备断开连接！");
                            return;
                        }
                        //替换waitingForTarget     结束


                        if(missionState!=1){
//                            logger.info("失败"+" --- "+"步骤1.  WCS监听 JXSPlc2WcsVar.AGV1_MissionState 是否 等于 3 失败");
//                            throw new Exception("agvPort1 waitingForTarget 异常");
                            return;
                        }else {
                            write(S7Client.S7_JXS, JXSWcs2PlcVar.AGV1_MissionState,3);
                            build.setContent("成功");
                            build.setStatus(100);
                        }



                        //调度逻辑 ------------------------------------- 结束 -------------------------------------
                        //执行回调接口
                        String result2 = HttpRequest.post(QGSConstant.agvPortCallbackUrl)
                                .header("Content-Type", "application/json")
                                .header("tenant-id", "1")
                                .header("Authorization", "Bearer test1")
                                .body(JSONObject.toJSONString(build))//表单内容
                                .timeout(20000)//超时，毫秒
                                .execute().body();
                        logger.info("成功"+" --- "+"AGV1 port 任务完成 ,wms 返回结果："+ result2);

                    }catch (Throwable e){
                        logger.info("agv1 port--- 出现异常 : {}",e.getMessage(),e);
                        JXSInfoCallBack build = new JXSInfoCallBack();
                        build.setContent("agv1: host:"+ S7Client.S7_JXS.getHost()+e.getMessage());
                        build.setStatus(-2);
                        build.setAgvPort("E01_1");
                        //执行回调接口
                        String result2 = HttpRequest.post(QGSConstant.agvPortCallbackUrl)
                                .header("Content-Type", "application/json")
                                .header("tenant-id", "1")
                                .header("Authorization", "Bearer test1")
                                .body(JSONObject.toJSONString(build))
                                .timeout(20000)
                                .execute().body();
                        logger.info("  ================== agv1 port--- 出现异常，现在返回给wms 结果："+ result2+"  ==================");
                    }
                }catch (Throwable e){
                    logger.info("  ================== agv1 port--- 出现异常，把结果返回给wms出现异常：   =================="+e.getMessage());
                }
            }
        },1,1, TimeUnit.SECONDS);


        agvPort2.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    try {
                        JXSInfoCallBack build = new JXSInfoCallBack();
                        build.setStatus(10);
                        build.setAgvPort("E01_2");

                        //调度逻辑 ------------------------------------- 开始 -------------------------------------

                        //Integer missionState = waitingForTarget(JXSPlc2WcsVar.AGV2_MissionState, 3);
                        Integer missionState = (Integer) read(S7Client.S7_JXS,JXSPlc2WcsVar.AGV2_MissionState);
                        if(missionState == null){
                            logger.info("失败"+" --- "+" wcs agvPort2 与设备断开连接！");
                            return;
                        }



                        if(missionState!=1){
//                            logger.info("失败"+" --- "+"  WCS监听 JXSPlc2WcsVar.AGV2_MissionState 是否 等于 3 失败");
//                            throw new Exception("agvPort2 waitingForTarget 异常");
                            return;
                        }else {
                            write(S7Client.S7_JXS, JXSWcs2PlcVar.AGV2_MissionState,3);
                            build.setContent("成功");
                            build.setStatus(100);
                        }



                        //调度逻辑 ------------------------------------- 结束 -------------------------------------
                        //执行回调接口
                        String result2 = HttpRequest.post(QGSConstant.agvPortCallbackUrl)
                                .header("Content-Type", "application/json")
                                .header("tenant-id", "1")
                                .header("Authorization", "Bearer test1")
                                .body(JSONObject.toJSONString(build))//表单内容
                                .timeout(20000)//超时，毫秒
                                .execute().body();
                        logger.info("成功"+" --- "+"AGV2 port 任务完成 ,wms 返回结果："+ result2);

                    }catch (Throwable e){
                        logger.info("agv2 port--- 出现异常 : {}",e.getMessage(),e);
                        JXSInfoCallBack build = new JXSInfoCallBack();
                        build.setContent("agv2: host:"+ S7Client.S7_JXS.getHost()+e.getMessage());
                        build.setStatus(-2);
                        build.setAgvPort("E01_2");
                        //执行回调接口
                        String result2 = HttpRequest.post(QGSConstant.agvPortCallbackUrl)
                                .header("Content-Type", "application/json")
                                .header("tenant-id", "1")
                                .header("Authorization", "Bearer test1")
                                .body(JSONObject.toJSONString(build))
                                .timeout(20000)
                                .execute().body();
                        logger.info("  ================== agv2 port--- 出现异常，现在返回给wms 结果："+ result2+"  ==================");
                    }
                }catch (Throwable e){
                    logger.info("  ================== agv2 port--- 出现异常，把结果返回给wms出现异常：   =================="+e.getMessage());
                }
            }
        },1,1, TimeUnit.SECONDS);

        agvPort3.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    try {
                        JXSInfoCallBack build = new JXSInfoCallBack();
                        build.setStatus(10);
                        build.setAgvPort("E01_3");

                        //调度逻辑 ------------------------------------- 开始 -------------------------------------

                        //Integer missionState = waitingForTarget(JXSPlc2WcsVar.AGV3_MissionState, 3);
                        Integer missionState = (Integer) read(S7Client.S7_JXS,JXSPlc2WcsVar.AGV3_MissionState);
                        if(missionState == null){
                            logger.info("失败"+" --- "+" wcs agvPort3 与设备断开连接！");
                            return;
                        }


                        if(missionState!=1){
//                            logger.info("失败"+" --- "+"  WCS监听 JXSPlc2WcsVar.AGV3_MissionState 是否 等于 3 失败");
//                            throw new Exception("agvPort3 waitingForTarget 异常");
                            return;
                        }else {

                            write(S7Client.S7_JXS, JXSWcs2PlcVar.AGV3_MissionState,3);
                            build.setContent("成功");
                            build.setStatus(100);
                        }



                        //调度逻辑 ------------------------------------- 结束 -------------------------------------
                        //执行回调接口

                        String result2 = HttpRequest.post(QGSConstant.agvPortCallbackUrl)
                                .header("Content-Type", "application/json")
                                .header("tenant-id", "1")
                                .header("Authorization", "Bearer test1")
                                .body(JSONObject.toJSONString(build))//表单内容
                                .timeout(20000)//超时，毫秒
                                .execute().body();
                        logger.info("成功"+" --- "+"AGV3 port 任务完成 ,wms 返回结果："+ result2);

                    }catch (Throwable e){
                        logger.info("agv3 port--- 出现异常 : {}",e.getMessage(),e);
                        JXSInfoCallBack build = new JXSInfoCallBack();
                        build.setContent("agv3: host:"+ S7Client.S7_JXS.getHost()+e.getMessage());
                        build.setStatus(-2);
                        build.setAgvPort("E01_3");
                        //执行回调接口
                        String result2 = HttpRequest.post(QGSConstant.agvPortCallbackUrl)
                                .header("Content-Type", "application/json")
                                .header("tenant-id", "1")
                                .header("Authorization", "Bearer test1")
                                .body(JSONObject.toJSONString(build))
                                .timeout(20000)
                                .execute().body();
                        logger.info("  ================== agv3 port--- 出现异常，现在返回给wms 结果："+ result2+"  ==================");
                    }
                }catch (Throwable e){
                    logger.info("  ================== agv3 port--- 出现异常，把结果返回给wms出现异常：   =================="+e.getMessage());
                }


            }
        },1,1, TimeUnit.SECONDS);

        agvPort4.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    try {
                        JXSInfoCallBack build = new JXSInfoCallBack();
                        build.setStatus(10);
                        build.setAgvPort("E01_4");

                        //调度逻辑 ------------------------------------- 开始 -------------------------------------

                        //Integer missionState = waitingForTarget(JXSPlc2WcsVar.AGV4_MissionState, 3);
                        Integer missionState = (Integer) read(S7Client.S7_JXS,JXSPlc2WcsVar.AGV4_MissionState);
                        if(missionState == null){
                            logger.info("失败"+" --- "+" wcs agvPort4 与设备断开连接！");
                            return;
                        }



                        if(missionState!=1){
//                            logger.info("失败"+" --- "+"  WCS监听 JXSPlc2WcsVar.AGV4_MissionState 是否 等于 3 失败");
//                            throw new Exception("agvPort4 waitingForTarget 异常");
                            return;
                        }else {

                            write(S7Client.S7_JXS, JXSWcs2PlcVar.AGV4_MissionState,3);
                            build.setContent("成功");
                            build.setStatus(100);
                        }



                        //调度逻辑 ------------------------------------- 结束 -------------------------------------
                        //执行回调接口

                        String result2 = HttpRequest.post(QGSConstant.agvPortCallbackUrl)
                                .header("Content-Type", "application/json")
                                .header("tenant-id", "1")
                                .header("Authorization", "Bearer test1")
                                .body(JSONObject.toJSONString(build))//表单内容
                                .timeout(20000)//超时，毫秒
                                .execute().body();
                        logger.info("成功"+" --- "+"AGV4 port 任务完成 ,wms 返回结果："+ result2);

                    }catch (Throwable e){
                        logger.info("agv4 port--- 出现异常 : {}",e.getMessage(),e);
                        JXSInfoCallBack build = new JXSInfoCallBack();
                        build.setContent("agv4: host:"+ S7Client.S7_JXS.getHost()+e.getMessage());
                        build.setStatus(-2);
                        build.setAgvPort("E01_4");
                        //执行回调接口
                        String result2 = HttpRequest.post(QGSConstant.agvPortCallbackUrl)
                                .header("Content-Type", "application/json")
                                .header("tenant-id", "1")
                                .header("Authorization", "Bearer test1")
                                .body(JSONObject.toJSONString(build))
                                .timeout(20000)
                                .execute().body();
                        logger.info("  ================== agv4 port--- 出现异常，现在返回给wms 结果："+ result2+"  ==================");
                    }
                }catch (Throwable e){
                    logger.info("  ================== agv4 port--- 出现异常，把结果返回给wms出现异常：   =================="+e.getMessage());
                }



            }
        },1,1, TimeUnit.SECONDS);

    }

    /**
     *
     * arg:
     *      JXSPlc2WcsVar 参数类型
     *      targetValue        目的值
     * return:
     *      2 s7 访问异常;
     *      1 成功;
     * */
    private Integer waitingForTarget(JXSPlc2WcsVar var, Integer targetValue) {
        Integer res = 0;
        while (true){
            try {

                Integer now = (Integer) read(S7Client.S7_JXS,var);
                //注意：即使now为null ，这里也不会抛出异常，这里很容易产生 空轮询。
                if(now == null){
                    Thread.sleep(2000);
                    throw new Exception("");
                }
                if(targetValue.equals(now)){
                    res = 1;
                    break;
                }
                Thread.sleep(200);
            }catch (Throwable e){
                logger.info("S7 数据采集 异常. 监听 变量 ："+var.getName()+" 为目标值："+targetValue+"失败");
                res = 2;
                break;
            }
        }
        return res;
    }




}